﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Web.Management;
using System.Globalization;

namespace DNA.Mvc.Management
{
    public class EntityWebEventProvider : BufferedWebEventProvider
    {
        protected string connectionName = "";
        private int _maxEventDetailsLength = -1;

        public override void Initialize(string name, System.Collections.Specialized.NameValueCollection config)
        {
            if (string.IsNullOrEmpty(config["connectionStringName"]))
                throw new ArgumentNullException("connectionStringName");

            connectionName = config["connectionStringName"];
            config.Remove("connectionStringName");

            if (config["maxEventDetailsLength"] != null)
            {
                int.TryParse(config["maxEventDetailsLength"].ToString(), out _maxEventDetailsLength);
                config.Remove("maxEventDetailsLength");
            }

            base.Initialize(name, config);
        }

        public override void ProcessEvent(WebBaseEvent raisedEvent)
        {
            if (base.UseBuffering)
            {
                base.ProcessEvent(raisedEvent);
            }
            else
            {
                var events=new List<WebBaseEvent>();
                events.Add(raisedEvent);
                this.SaveToDB(new WebBaseEventCollection(events), 0, new DateTime(0));
            }
        }

        public override void ProcessEventFlush(WebEventBufferFlushInfo flushInfo)
        {
            this.SaveToDB(flushInfo.Events, flushInfo.EventsDiscardedSinceLastNotification, flushInfo.LastNotificationUtc);
        }

        protected virtual void SaveToDB(WebBaseEventCollection events, int eventsDiscardedByBuffer, DateTime lastNotificationUtc)
        {
            using (var db = new LogDB(connectionName))
            {
                Exception errorException = null;
                WebRequestInformation requestInformation = null;
                string detail = null;
                WebApplicationInformation applicationInformation = WebBaseEvent.ApplicationInformation;

                foreach (WebBaseEvent e in events)
                {
                    var log = new EventLogEntry()
                    {
                        EventID = e.EventID.ToString("N", CultureInfo.InstalledUICulture),
                        EventTimeUtc = e.EventTimeUtc,
                        EventTime = e.EventTime,
                        EventType = e.GetType().ToString(),
                        EventSequence = e.EventSequence,
                        EventOccurrence = e.EventOccurrence,
                        EventCode = e.EventCode,
                        EventDetailCode = e.EventDetailCode,
                        Message = e.Message,
                        ApplicationPath=applicationInformation.ApplicationPath,
                        ApplicationVirtualPath=applicationInformation.ApplicationVirtualPath,
                        MachineName=applicationInformation.MachineName
                    };

                    if (e is WebRequestEvent)
                    {
                        requestInformation = ((WebRequestEvent)e).RequestInformation;
                    }
                    else if (e is WebRequestErrorEvent)
                    {
                        requestInformation = ((WebRequestErrorEvent)e).RequestInformation;
                    }
                    else if (e is WebErrorEvent)
                    {
                        requestInformation = ((WebErrorEvent)e).RequestInformation;
                    }
                    else if (e is WebAuditEvent)
                    {
                        requestInformation = ((WebAuditEvent)e).RequestInformation;
                    }

                    if (e is WebBaseErrorEvent)
                    {
                        errorException = ((WebBaseErrorEvent)e).ErrorException;
                    }

                    if (requestInformation != null)
                    {
                        log.RequestUrl = requestInformation.RequestUrl;
                        if ((requestInformation.Principal != null) && (requestInformation.Principal.Identity != null))
                            log.UserName = requestInformation.Principal.Identity.Name;
                    }

                    if (errorException != null)
                        log.ExceptionType = errorException.GetType().ToString();

                    detail = e.ToString();
                    if ((this._maxEventDetailsLength != -1) && (detail.Length > this._maxEventDetailsLength))
                    {
                        detail = detail.Substring(0, this._maxEventDetailsLength);
                    }

                    log.Detail = detail;
                    db.WebEvents.Add(log);
                }
                db.SaveChanges();
            }
        }

        public override void Shutdown()
        {
            try
            {
                this.Flush();
            }
            finally
            {
                base.Shutdown();
            }
        }
    }
}
